package main

import (
	_ "gorm.io/driver/mysql"
	"gorm.io/gorm"
)

//主键：gorm默认使用名为ID的字段作为表的主键
//表名：默认就是结构体名称的复数
//userinfo结构体对应数据表(不用gorm.Model自行定义模型)
//type UserInfo struct {
//	ID     uint
//	Name   string
//	Gender string
//	Hobby  string
//}

//	在使用ORM工具时，通常需要在代码中定义模型（Models）与数据库中的数据表进行映射，在gorm 中模型通常是正常定义的结构体、基本的go类型或指针，同时也支持sql.Scanner及driver.Valuer
//
// 采用gorm.Model定义数据模型
//
//	type Model struct{
//		ID uint `gorm:"primary_key"`  //gorm:"primary_key" 标记当前这个id是自增的
//		CreateAt time.Time
//		UpdateAt time.Time
//		Deletet *time.Time
//	}
//
// 枫枫知道-学习gorm--单表操作
type Student struct {
	ID    uint    `gorm:"size:10"`
	Name  string  `gorm:"size:16;not null;comment:姓名"`
	Age   int     `gorm:"size:3;not null;comment:年龄"`
	Email *string `gorm:"size:128;comment:邮箱;unique"` //使用指针是为了存空值
}

// BeforeCreate 钩子函数hook 再执行前需要做的事情
func (user *Student) BeforeCreate(tx *gorm.DB) (err error) {
	email := "test@qq.com"
	user.Email = &email
	return nil
}
func main() {
	//在执行这个创建时，会调用上面定义的钩子函数 给email赋默认值test@qq.com
	DB.Create(&Student{
		Name: "test",
		Age:  24,
	})
	//gorm--单表增删改查
	//	1.1单个增加 先实例化一个student对象u1
	//email := "1050444273.com"
	//u1 := Student{
	//	Name:  "ddd",
	//	Age:   23,
	//	Email: &email,
	//}
	//err := DB.Create(&u1).Error
	//if err != nil {
	//	fmt.Print("添加失败")
	//}
	//1.2 批量插入
	//var studentList []Student
	//for i := 0; i < 10; i++ {
	//	studentList = append(studentList, Student{
	//		Name:  fmt.Sprintf("学号%d", i+1),
	//		Age:   20 + i + 1,
	//		Email: nil,
	//	})
	//}
	//err := DB.Create(&studentList).Error
	//if err != nil {
	//	fmt.Print("添加失败")
	//}
	// 2.1查询单条记录的数据
	//var u Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//DB.Take(&u) // 等价于--> SELECT * FROM `students` LIMIT 1 查询表中第一条数据
	//DB.First(&u) //查询表中第一条数据 等价于 SELECT * FROM `students` ORDER BY `students`.`id` LIMIT 1
	//fmt.Println(u)
	// 2.2根据主键查询数据
	//DB.Take(&u, 32)
	//// 2.3根据条件查
	//DB.Take(&u, "name = ?", "wxd")
	//DB.Take(&u, fmt.Sprintf("name= '%s'", "wxd"))
	//fmt.Println(u)
	//3.1查询多条数据
	//var u []Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//count := DB.Find(&u).RowsAffected //查找出来的总条数
	//fmt.Println(count)
	//for _, student := range u { //循环打印每条数据
	//	fmt.Println(student)
	//}
	//data, _ := json.Marshal(u) //将查出来的结果序列化为json格式再打印
	//fmt.Println(string(data))
	//3.2 根据id列表查询多条数据
	//err := DB.Find(&u, []int{1, 31, 34}).Error //查询主键id为1，31，34对应的数据
	//err := DB.Find(&u, "id in (?)", []int{1, 31, 34}).Error
	//err := DB.Find(&u, "name in ?", []string{"ddd", "??2", "??3"}).Error
	//if err != nil {
	//	fmt.Print("查询失败")
	//}
	//fmt.Println(u)
	// 更新
	//4.1单个记录的更新 --- save方法 ---先查找再更新
	//等价于 以下两个sql
	//SELECT * FROM `students` WHERE `students`.`id` = 1 LIMIT 1
	//UPDATE `students` SET `name`='更新测试',`age`=23,`email`='1050444273.com' WHERE `id` = 1
	//var u Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//email := "1050444274@qq.com"
	//DB.Take(&u, 32)
	//u.Name = "更新测试"
	//u.Email = &email
	//DB.Save(&u)
	//fmt.Println(u)
	//4.2 只更新指定的字段 --- save方法 ---先查找再更新
	//等价于以下两个sql
	//SELECT * FROM `students` WHERE `students`.`id` = 33 LIMIT 1
	//UPDATE `students` SET `name`='更新测试' WHERE `id` = 33
	//var u Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//email := "1050444274@qq.com"
	//DB.Take(&u, 33)
	//u.Name = "更新测试"
	//u.Email = &email
	//DB.Select("name").Save(&u)
	//fmt.Println(u)
	// 4.3 批量更新单个字段 update
	//等价于以下两个sql
	//SELECT * FROM `students` WHERE id in (35,36,37)
	////UPDATE `students` SET `name`='批量更新测试' WHERE id in (35,36,37) AND `id` IN (35,36,37) [{35 批量更新测试 24 <nil>} {36 批量更新测试 25 <nil>} {37 批量更新测试 26 <nil>}]
	//var u []Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//DB.Find(&u, "id in ?", []int{35, 36, 37}).Update("name", "批量更新测试")
	//fmt.Println(u)
	// 4.3 批量更新多列或多字段 updates
	//批量更新主键id为38 39对应的年龄及姓名的信息 实际更新的是结构体，在结构体中传入什么，则就更新什么
	//等价于以下两个sql
	//SELECT * FROM `students` WHERE id in (38,39)
	//UPDATE `students` SET `name`='test',`age`=25 WHERE id in (38,39) AND `id` IN (38,39) [{38 test 25 <nil>} {39 test 25 <nil>}]
	//var u []Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//方法一
	//DB.Find(&u, "id in ?", []int{38, 39}).Updates(Student{
	//	Name: "test",
	//	Age:  25,
	//})
	//fmt.Println(u})
	//方式二、采用model与where更新 与第一种方式相比少了第一步查询 可以提高运行速率
	//更新Student这个结构体中年龄等于30的数据中的姓名为model更新测试
	//等价于这个sql UPDATE `students` SET `name`='model更新测试' WHERE age=30
	//err := DB.Model(&Student{}).Where("age=?", 30).Update("name", "model更新测试").Error
	//if err != nil {
	//	fmt.Println("更新失败")
	//}
	////4.4 批量更新多列或多字段 updates 用map方式实现
	//var u []Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//方法一
	//DB.Find(&u, "id in ?", []int{38, 39}).Updates(map[string]any{
	//	"name": "map方式实现",
	//},
	//)
	//方法二
	//DB.Model(Student{}).Where("age=?", 29).Updates(map[string]any{
	//	"name": "updates测试",
	//})
	//fmt.Println(u)
	//5.1 根据主键单个删除
	//var u Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//DB.Delete(&u, 41) //41是主键id号
	//5.2 根据主键批量删除
	//var u Student
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//DB.Delete(&u, []int{40, 39}) //40,39是主键id号
	//	根据条件删除
	//DB = DB.Session(&gorm.Session{
	//	Logger: mysqlLogger,
	//})
	//DB.Model(&Student{}).Where("id=?", 38).Delete(&Student{})
	//DB.Where("email=?", "1050444273.com").Delete(&Student{})
}
